home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / FLTK-1.0.6 / src / Fl_Scroll.cxx < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-07  |  6.6 KB  |  236 lines

  1. //
  2. // "$Id: Fl_Scroll.cxx,v 1.7 1999/01/07 19:17:26 mike Exp $"
  3. //
  4. // Scroll widget for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-1999 by Bill Spitzak and others.
  7. //
  8. // This library is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU Library General Public
  10. // License as published by the Free Software Foundation; either
  11. // version 2 of the License, or (at your option) any later version.
  12. //
  13. // This library is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. // Library General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Library General Public
  19. // License along with this library; if not, write to the Free Software
  20. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  21. // USA.
  22. //
  23. // Please report all bugs and problems to "fltk-bugs@easysw.com".
  24. //
  25.  
  26. #include <FL/Fl.H>
  27. #include <FL/Fl_Scroll.H>
  28. #include <FL/fl_draw.H>
  29.  
  30. // Insure the scrollbars are the last children:
  31. void Fl_Scroll::fix_scrollbar_order() {
  32.   Fl_Widget*const* a = array();
  33.   if (a[children()-1] != &scrollbar) {
  34.     Fl_Widget** a = (Fl_Widget**)array();
  35.     int i,j; for (i = j = 0; j < children(); j++)
  36.       if (a[j] != &hscrollbar && a[j] != &scrollbar) a[i++] = a[j];
  37.     a[i++] = &hscrollbar;
  38.     a[i++] = &scrollbar;
  39.   }
  40. }
  41.  
  42. void Fl_Scroll::draw_clip(void* v,int X, int Y, int W, int H) {
  43.   fl_clip(X,Y,W,H);
  44.   Fl_Scroll* s = (Fl_Scroll*)v;
  45.   // erase background if there is a boxtype:
  46.   if (s->box() && !(s->damage()&FL_DAMAGE_ALL)) {
  47.     fl_color(s->color());
  48.     fl_rectf(X,Y,W,H);
  49.   }
  50.   Fl_Widget*const* a = s->array();
  51.   int R = X; int B = Y; // track bottom & right edge of all children
  52.   for (int i=s->children()-2; i--;) {
  53.     Fl_Widget& o = **a++;
  54.     s->draw_child(o);
  55.     s->draw_outside_label(o);
  56.     if (o.x()+o.w() > R) R = o.x()+o.w();
  57.     if (o.y()+o.h() > B) B = o.y()+o.h();
  58.   }
  59.   // fill any area to right & bottom of widgets:
  60.   if (R < X+W && B > Y) {
  61.     fl_color(s->color());
  62.     fl_rectf(R,Y,X+W-R,B-Y);
  63.   }
  64.   if (B < Y+H) {
  65.     fl_color(s->color());
  66.     fl_rectf(X,B,W,Y+H-B);
  67.   }
  68.   fl_pop_clip();
  69. }
  70.  
  71. void Fl_Scroll::bbox(int& X, int& Y, int& W, int& H) {
  72.   X = x()+Fl::box_dx(box());
  73.   Y = y()+Fl::box_dy(box());
  74.   W = w()-Fl::box_dw(box());
  75.   H = h()-Fl::box_dh(box());
  76.   if (scrollbar.visible()) {
  77.     W -= scrollbar.w();
  78.     if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar.w();
  79.   }
  80.   if (hscrollbar.visible()) {
  81.     H -= hscrollbar.h();
  82.     if (scrollbar.align() & FL_ALIGN_TOP) Y += hscrollbar.h();
  83.   }
  84. }
  85.  
  86. void Fl_Scroll::draw() {
  87.   fix_scrollbar_order();
  88.   int X,Y,W,H; bbox(X,Y,W,H);
  89.  
  90.   uchar d = damage();
  91.  
  92.   if (d & FL_DAMAGE_ALL) { // full redraw
  93.     draw_box(box(),x(),y(),w(),h(),color());
  94.     draw_clip(this, X, Y, W, H);
  95.   } else {
  96.     if (d & FL_DAMAGE_SCROLL) { // scroll the contents:
  97.       fl_scroll(X, Y, W, H, oldx-xposition_, oldy-yposition_, draw_clip, this);
  98.     }
  99.     if (d & FL_DAMAGE_CHILD) { // draw damaged children
  100.       fl_clip(X, Y, W, H);
  101.       Fl_Widget*const* a = array();
  102.       for (int i=children()-2; i--;) update_child(**a++);
  103.       fl_pop_clip();
  104.     }
  105.   }
  106.  
  107.   // accumulate bounding box of children:
  108.   int l = X; int r = X; int t = Y; int b = Y;
  109.   Fl_Widget*const* a = array();
  110.   for (int i=children()-2; i--;) {
  111.     Fl_Object* o = *a++;
  112.     if (o->x() < l) l = o->x();
  113.     if (o->y() < t) t = o->y();
  114.     if (o->x()+o->w() > r) r = o->x()+o->w();
  115.     if (o->y()+o->h() > b) b = o->y()+o->h();
  116.   }
  117.  
  118.   // turn the scrollbars on and off as necessary:
  119.   for (int z = 0; z<2; z++) {
  120.     if ((type()&VERTICAL) && (type()&ALWAYS_ON || t < Y || b > Y+H)) {
  121.       if (!scrollbar.visible()) {
  122.     scrollbar.set_visible();
  123.     W -= scrollbar.w();
  124.     d = FL_DAMAGE_ALL;
  125.       }
  126.     } else {
  127.       if (scrollbar.visible()) {
  128.     scrollbar.clear_visible();
  129.     draw_clip(this,
  130.           scrollbar.align()&FL_ALIGN_LEFT ? X-scrollbar.w() : X+W,
  131.           Y, scrollbar.w(), H);
  132.     W += scrollbar.w();
  133.     d = FL_DAMAGE_ALL;
  134.       }
  135.     }
  136.     if ((type()&HORIZONTAL) && (type()&ALWAYS_ON || l < X || r > X+W)) {
  137.       if (!hscrollbar.visible()) {
  138.     hscrollbar.set_visible();
  139.     H -= hscrollbar.h();
  140.     d = FL_DAMAGE_ALL;
  141.       }
  142.     } else {
  143.       if (hscrollbar.visible()) {
  144.     hscrollbar.clear_visible();
  145.     draw_clip(this, X,
  146.           scrollbar.align()&FL_ALIGN_TOP ? Y-hscrollbar.h() : Y+H,
  147.           W, hscrollbar.h());
  148.     H += hscrollbar.h();
  149.     d = FL_DAMAGE_ALL;
  150.       }
  151.     }
  152.   }
  153.  
  154.   scrollbar.resize(scrollbar.align()&FL_ALIGN_LEFT ? X-scrollbar.w() : X+W,
  155.            Y, scrollbar.w(), H);
  156.   scrollbar.value(oldy = yposition_ = (Y-t), H, 0, b-t);
  157.  
  158.   hscrollbar.resize(X,
  159.             scrollbar.align()&FL_ALIGN_TOP ? Y-hscrollbar.h() : Y+H,
  160.             W, hscrollbar.h());
  161.   hscrollbar.value(oldx = xposition_ = (X-l), W, 0, r-l);
  162.  
  163.   // draw the scrollbars:
  164.   if (d & FL_DAMAGE_ALL) {
  165.     draw_child(scrollbar);
  166.     draw_child(hscrollbar);
  167.     if (scrollbar.visible() && hscrollbar.visible()) {
  168.       // fill in the little box in the corner
  169.       fl_color(color());
  170.       fl_rectf(scrollbar.x(), hscrollbar.y(), scrollbar.w(), hscrollbar.h());
  171.     }
  172.   } else {
  173.     update_child(scrollbar);
  174.     update_child(hscrollbar);
  175.   }
  176. }
  177.  
  178. void Fl_Scroll::resize(int X, int Y, int W, int H) {
  179.   fix_scrollbar_order();
  180.   // move all the children:
  181.   Fl_Widget*const* a = array();
  182.   for (int i=children()-2; i--;) {
  183.     Fl_Object* o = *a++;
  184.     o->position(o->x()+X-x(), o->y()+Y-y());
  185.   }
  186.   Fl_Widget::resize(X,Y,W,H);
  187. }
  188.  
  189. void Fl_Scroll::position(int X, int Y) {
  190.   int dx = xposition_-X;
  191.   int dy = yposition_-Y;
  192.   if (!dx && !dy) return;
  193.   xposition_ = X;
  194.   yposition_ = Y;
  195.   Fl_Widget*const* a = array();
  196.   for (int i=children(); i--;) {
  197.     Fl_Widget* o = *a++;
  198.     if (o == &hscrollbar || o == &scrollbar) continue;
  199.     o->position(o->x()+dx, o->y()+dy);
  200.   }
  201.   damage(FL_DAMAGE_SCROLL);
  202. }
  203.  
  204. void Fl_Scroll::hscrollbar_cb(Fl_Widget* o, void*) {
  205.   Fl_Scroll* s = (Fl_Scroll*)(o->parent());
  206.   s->position(int(((Fl_Scrollbar*)o)->value()), s->yposition());
  207. }
  208.  
  209. void Fl_Scroll::scrollbar_cb(Fl_Widget* o, void*) {
  210.   Fl_Scroll* s = (Fl_Scroll*)(o->parent());
  211.   s->position(s->xposition(), int(((Fl_Scrollbar*)o)->value()));
  212. }
  213.  
  214. #define SLIDER_WIDTH 17
  215.  
  216. Fl_Scroll::Fl_Scroll(int X,int Y,int W,int H,const char* L)
  217.   : Fl_Group(X,Y,W,H,L), 
  218.     scrollbar(X+W-SLIDER_WIDTH,Y,SLIDER_WIDTH,H-SLIDER_WIDTH),
  219.     hscrollbar(X,Y+H-SLIDER_WIDTH,W-SLIDER_WIDTH,SLIDER_WIDTH) {
  220.   type(BOTH);
  221.   xposition_ = 0;
  222.   yposition_ = 0;
  223.   hscrollbar.type(FL_HORIZONTAL);
  224.   hscrollbar.callback(hscrollbar_cb);
  225.   scrollbar.callback(scrollbar_cb);
  226. }
  227.  
  228. int Fl_Scroll::handle(int event) {
  229.   fix_scrollbar_order();
  230.   return Fl_Group::handle(event);
  231. }
  232.  
  233. //
  234. // End of "$Id: Fl_Scroll.cxx,v 1.7 1999/01/07 19:17:26 mike Exp $".
  235. //
  236.